﻿#include <algorithm>
#include <cctype>
#include <string>
#include <string_view>
#include <fstream>
#include <sstream>
#include "Map.h"

Cell* Map::rowPoint(int row, int prep)
{
    // 行：直接用原地址，用mapTemp记录变化
    if (prep == 0)
        for (int c = 0; c < cols; ++c) mapTemp[row][c] = map[row][c];
    else
        for (int c = 0; c < cols; ++c)
            if (map[row][c] != mapTemp[row][c]) colFlags[c].needProc = true;

    return map[row];
}

Cell* Map::colPoint(int col, int prep)
{
    // 列：用mapTemp旋转行列，需要回写
    if (prep == 0)
        for (int r = 0; r < rows; ++r) mapTemp[col][r] = map[r][col];
    else
        for (int r = 0; r < rows; ++r)
            if (map[r][col] != mapTemp[col][r])
            {
                map[r][col] = mapTemp[col][r];
                rowFlags[r].needProc = true;
            }

    return mapTemp[col];
}

void Map::print(std::ostream& stream)
{
    for (int r = 0; r < rows; ++r)
        stream << std::string_view((char*)map[r], cols) << std::endl;   // c++17 string_view
}

int Map::readALine(Flags& fl, std::istream& fs)         // flag太多返回 -1
{
	std::string s;
    while (std::getline(fs, s))                         // 跳过空行、注释
		if (!s.empty() && std::isdigit(s[0])) break;

	std::istringstream ss(s);
	int t, sum = 0, count = 0;
	while (ss >> t)
	{
		if (t == 0) break;
        if (count >= maxF) return -1;
		fl.f[count++].n = t;
		sum += t;
        ss.get();       // 跳过分隔符，如果用空格为分隔符可以不用
	}
    fl.len = count;
    if (count > maxFlagLen) maxFlagLen = count;
	return sum;
}

//  文件打开错误返回1，格子太多返回2，flag太多返回3，计数错误返回4
int Map::readFromFile(const char* fn)
{
	std::ifstream fs(fn);
	if (!fs) return 1;

	std::string s;
	while (std::getline(fs, s))
		if (!s.empty() && std::isdigit(s[0])) break;
	std::istringstream ss(s);
	int rotate;
	ss >> cols >> rows >> rotate;
    if (cols <=0 || cols > maxN || rows <=0 || rows > maxN)	return 2;

    int sum = 0, t;
    maxFlagLen = 0;
    for (int c = 0; c < cols; ++c)
	{
        if ((t = readALine(colFlags[c], fs)) < 0) return 3;
		sum += t;
	}
	maxColFlagLen = maxFlagLen;
	maxFlagLen =0;
	for (int r = 0; r < rows; ++r)
	{
        if ((t = readALine(rowFlags[r], fs)) < 0) return 3;
		sum -= t;
	}
	maxRowFlagLen = maxFlagLen;
	fs.close();
	// 正常情况 sum 应 =0
	if (sum) return 4;

	// 文件第一行第三个数代表旋转
	switch (rotate)
	{
		case -1 :
		case -90 :
		case 270 :
			rotate90();
		case 2 :
		case 180 :
			rotate90();
		case 1:
		case 90 :
			rotate90();
	}

	mapClear();
	return 0;
}

// 旋转90度
void Map::rotate90()
{
	Flags tmpFlags[maxN];
    for (int c = 0; c < cols; ++c) tmpFlags[c] = colFlags[c].reverse();
    for (int r = 0; r < rows; ++r) colFlags[r] = rowFlags[rows - r - 1];
    for (int c = 0; c < cols; ++c) rowFlags[c] = tmpFlags[c];
	std::swap(cols, rows);
}

 void Map::mapClear()
 {
    std::fill_n((Cell*)map, maxN * maxN, Cell::Unknow);
    for (Flags& c : colFlags) c.clear();
    for (Flags& r : rowFlags) r.clear();
 }

